package br.ufes.ceunes.poo.model.pojo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * Classe para objetos do tipo Cliente, onde serão contidos, identificadores e
 * métodos para o mesmo.
 */
@Entity
@Table

public class Fornecedor implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToMany
    @JoinTable(name = "produto_do_fornecedor", joinColumns = {
        @JoinColumn(name = "fornecedor_id")}, inverseJoinColumns = {
        @JoinColumn(name = "produto_id")})
    private final List<Produto> produtos;

    @Column(nullable = false)
    private String nome;

    @Column(nullable = false, unique = true)
    private String cnpj;

    @Column
    private String endereco;

    /**
     * Método para instanciar a lista de pedidos do Fornecedor.
     */
    public Fornecedor() {
        produtos = new ArrayList();
    }

    /**
     * Método para construção do Fornecedor
     *
     * obs.: reaproveita o construtor anterior
     *
     * @param produtos - atribui um lista de produtos
     */

    public Fornecedor(Produto... produtos) {
        this();
        this.produtos.addAll(Arrays.asList(produtos));
    }

    /**
     * Método para construção do Fornecedor.
     *
     * obs.: reaproveita o construtor anterior
     *
     * @param nome - atribui o nome da empresa fornecedora
     * @param cnpj - atribui o cnpj da empresa fornecedora
     * @param endereco - atribui o endereco da empresa fornecedora
     *
     */
    public Fornecedor(String nome, String cnpj, String endereco) {
        this();
        this.nome = nome;
        this.cnpj = cnpj;
        this.endereco = endereco;
    }

    /**
     * Método para construção do Fornecedor.
     *
     * obs.: reaproveita o construtor anterior
     *
     * @param id - atribui uma udentificação
     * @param nome - atribui o nome da empresa fornecedora
     * @param cnpj - atribui o cnpj da empresa fornecedora
     * @param endereco - atribui o endereco da empresa fornecedora
     */
    public Fornecedor(Integer id, String nome, String cnpj, String endereco) {
        this(nome, cnpj, endereco);
        this.id = id;
    }

    /**
     * O metodo adiciona um item
     *
     * @param produto recebe um prduto como parametro
     * @return boolean - Caso o item ja exista na lista ou lista vazia retornará
     * false,caso contrário retorna true.
     */
    public boolean adicionarItem(Produto produto) {

        if (produtos.isEmpty()) {
            produtos.add(produto);
            return true;
        }

        if (produtos.contains(produto)) {
            return false;
        } else {
            produtos.add(produto);
            return true;
        }

    }

    /**
     * O metodo remove um item.
     *
     * @param produto recebe um produto
     * @return boolean. Caso o item for encontrado e removido retorna true, caso
     * contrario retorna false.
     */
    public boolean removerItem(Produto produto) {

        if (produtos.isEmpty() == true) {
            return false;
        }

        if (produtos.contains(produto.getId()) == false) {
            return false;
        } else {
            produtos.remove(produto.getId());
            return true;

        }

    }

    /**
     * Método para alterar o ID do Fornecedor
     *
     * @param id - id do Fornecedor
     */
    public void setId(int id) {
        if (this.id == null) {
            this.id = id;
        }
    }

    /**
     * Método para retornar o ID do Fornecedor
     *
     * @return id - id do Fornecedor
     */
    public Integer getId() {
        return this.id;
    }

    /**
     * Método para retornar o nome do Fornecedor
     *
     * @return String
     */
    public String getNome() {
        return nome;
    }

    /**
     * Método para alterar o nome do Fornecedor
     *
     * @param nome - nome do Fornecedor
     */
    public void setNome(String nome) {
        this.nome = nome;
    }

    /**
     * Método para retornar o CNPJ do fornecedor
     *
     * @return String
     */
    public String getCnpj() {
        return cnpj;
    }

    /**
     * Método para alterar o cnpj do Fornecedor
     *
     * @param cnpj - cnpj do Fornecedor
     */
    public void setCnpj(String cnpj) {
        this.cnpj = cnpj;
    }

    /**
     * Método para retornar o endereço do fornecedor
     *
     * @return String - endereço do Fornecedor
     */
    public String getEndereco() {
        return endereco;
    }

    /**
     * Método para alterar o endereço do Fornecedor
     *
     * @param endereco - endereço do Fornecedor
     */
    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    /**
     * Método para retornar o lista de produtos
     *
     * @return List - lista de produtos
     */
    public List<Produto> getProdutos() {
        return Collections.unmodifiableList(produtos);
    }

    /**
     * Sobrescrição do método hashCode para agilizar a busca em collections
     *
     * @return hash - o método retorna um codigo hash de um objeto
     */
    @Override
    public int hashCode() {
        int hash = 5;
        hash = 73 * hash + Objects.hashCode(this.id);
        return hash;
    }

    /**
     * Sobrescrição do método equals
     *
     * @param obj - objeto para comparação
     * @return boolean - false se não encontra, true caso contrário
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Fornecedor other = (Fornecedor) obj;
        return Objects.equals(this.id, other.id);
    }

}
